package com.itheima.pinda.file.strategy.impl;

import com.itheima.pinda.exception.BizException;
import com.itheima.pinda.exception.code.ExceptionCode;
import com.itheima.pinda.file.domain.FileDeleteDO;
import com.itheima.pinda.file.entity.File;
import com.itheima.pinda.file.enumeration.IconType;
import com.itheima.pinda.file.properties.FileServerProperties;
import com.itheima.pinda.file.strategy.FileStrategy;
import com.itheima.pinda.file.utils.FileDataTypeUtil;
import com.itheima.pinda.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 抽象文件策略处理类
 *
 * @author:ivan.liu
 */
@Slf4j
public abstract class AbstractFileStrategy implements FileStrategy {
    private static final String FILE_SPLIT=".";

    @Autowired
    protected FileServerProperties fileProperties;

    //内部类没有注入，根据存储策略具体赋值
    protected FileServerProperties.Properties properties;

    /**
     * 文件上传
     * @param multipartFile
     * @return
     */
    @Override
    public File upload(MultipartFile multipartFile) {
        try {
            //获得上传文件的原始名称
            String originalFilename = multipartFile.getOriginalFilename();
            if (!originalFilename.contains(FILE_SPLIT)){
                //文件名中没有.则直接抛出异常
                throw BizException.wrap(ExceptionCode.BASE_VALID_PARAM.build("上传文件名称缺少后缀"));
            }
            //将MultipartFile封装为File对象，便于插入数据库
            File file = File.builder()
                    //封装File对象相关属性
                    .isDelete(false)
                    .size(multipartFile.getSize())
                    .contextType(multipartFile.getContentType())
                    .dataType(FileDataTypeUtil.getDataType(multipartFile.getContentType()))//通过Util判断比对
                    .submittedFileName(multipartFile.getOriginalFilename())
                    .ext(FilenameUtils.getExtension(multipartFile.getOriginalFilename()))
                    .build();
            //设置文件图标，用于云盘展示
            file.setIcon(IconType.getIcon(file.getExt()).getIcon());
            LocalDateTime now = LocalDateTime.now();
            //设置文件创建时间
            file.setCreateMonth(DateUtils.formatAsYearMonthEn(now));
            file.setCreateWeek(DateUtils.formatAsYearWeekEn(now));
            file.setCreateDay(DateUtils.formatAsDateEn(now));

            //具体上传逻辑
            uploadFile(file,multipartFile);
            return file;
        } catch (Exception e) {
            log.error("e = {}",e);
            throw BizException.wrap(ExceptionCode.BASE_VALID_PARAM.build("文件上传失败"));
        }
    }

    /**
     * 实际上传逻辑，由子类具体实现
     * @param file
     * @param multipartFile
     * @return
     */
    public abstract void uploadFile(File file,MultipartFile multipartFile) throws Exception;

    /**
     * 文件下载
     * @param list
     * @return
     */
    @Override
    public boolean delete(List<FileDeleteDO> list) {
        if (list==null||list.isEmpty()){
            return true;
        }

        boolean flag = false;
        for (FileDeleteDO fileDeleteDO : list) {
            try {
                delete(fileDeleteDO);
                flag = true;
            } catch (Exception e) {
                log.error("e={}",e);
            }
        }
        return flag;
    }

    /**
     * 实际删除逻辑，由子类具体实现
     * @param fileDeleteDO
     */
    public abstract void delete(FileDeleteDO fileDeleteDO);

    /**
     * 获取下载地址的前缀部分
     * @return
     */
    protected String getUriPrefix(){
        if (StringUtils.isNotEmpty(properties.getUriPrefix())){
            return properties.getUriPrefix();
        }else {
            //如果没有前缀说明为oss存储策略，采用Endpoint作为前缀
            return properties.getEndpoint();
        }
    }
}
